﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Windows.Forms;
using System.Xml;

namespace SZJT.Framework.Adapter
{
    public class ComponentConfiguration
    {
        static readonly XmlDocument _xmlDoc = new XmlDocument();

        /// <summary>
        /// 配置文件的路径
        /// </summary>
        public string ComponentPath
        {
            get
            {
                try
                {
                    string path;
                    if (null == HttpContext.Current)
                    {
                        var di = new DirectoryInfo(Application.StartupPath);
                        path = di.Parent.Parent.FullName + "\\Configs\\Component.xml";
                        //path = "..\\Configs\\Component.xml";
                    }
                    else
                        path = HttpContext.Current.Server.MapPath("~/Configs/Component.xml");

                    LoggerHelper.WriteCodePointInfo(path);
                    return path;
                }
                catch
                {
                    LoggerHelper.WriteCodePointInfo("ComponentPath 初始化错误！");
                    return string.Empty;
                }
            }
        }

        public ComponentConfiguration()
        {
            new ComponentConfiguration(string.Empty);
        }

        public ComponentConfiguration(string path)
        {
            _xmlDoc.Load(string.IsNullOrEmpty(path) ? ComponentPath : path);
        }

        public Component GetComponent()
        {
            try
            {
                var componentNode = _xmlDoc.DocumentElement;
                var component = new Component();
                var adapterList = componentNode.SelectNodes("adapter");
                var taskList = componentNode.SelectNodes("task");
                var pluginList = componentNode.SelectNodes("plugin");
                var synServiceList = componentNode.SelectNodes("synService");
                component.AccountName = componentNode.Attributes["accountName"] == null ? string.Empty : componentNode.Attributes["accountName"].Value;
                component.Password = componentNode.Attributes["password"] == null ? string.Empty : componentNode.Attributes["password"].Value;
                component.CertName = componentNode.Attributes["certName"] == null ? string.Empty : componentNode.Attributes["certName"].Value;
                if (string.IsNullOrEmpty(component.AccountName) || string.IsNullOrEmpty(component.CertName))
                    throw new Exception("组件配置节有为空必填项！");
                foreach (var adapter in from XmlNode adapterNode in adapterList
                                        select new Adapter
                                        {
                                            Type = adapterNode.Attributes["type"] == null ? string.Empty : adapterNode.Attributes["type"].Value,
                                            Guid = adapterNode.Attributes["guid"] == null ? string.Empty : adapterNode.Attributes["guid"].Value,
                                            Protocol = adapterNode.Attributes["protocol"] == null ? string.Empty : adapterNode.Attributes["protocol"].Value,
                                            TaskList = adapterNode.Attributes["tasklist"] == null ? string.Empty : adapterNode.Attributes["tasklist"].Value
                                        })
                {
                    if (string.IsNullOrEmpty(adapter.Guid) || string.IsNullOrEmpty(adapter.Type))
                        throw new Exception(component.AccountName + "组件的适配器配置节有为空必填项！");
                    component.Adapters.Add(adapter);
                }
                foreach (var task in from XmlNode taskNode in taskList
                                     select new Task
                                     {
                                         TaskGuid = taskNode.Attributes["taskGuid"] == null ? string.Empty : taskNode.Attributes["taskGuid"].Value,
                                         AdapterGuid = taskNode.Attributes["adapterGuid"] == null ? string.Empty : taskNode.Attributes["adapterGuid"].Value
                                     })
                {
                    if (string.IsNullOrEmpty(task.TaskGuid) || string.IsNullOrEmpty(task.AdapterGuid))
                        throw new Exception(component.AccountName + "组件的应用标识配置节有为空必填项！");
                    component.Tasks.Add(task);
                }
                foreach (var plugin in from XmlNode pluginNode in pluginList
                                       select new Plugin
                                       {
                                           TaskGuid = pluginNode.Attributes["taskGuid"] == null ? string.Empty : pluginNode.Attributes["taskGuid"].Value,
                                           Type = pluginNode.Attributes["type"] == null ? string.Empty : pluginNode.Attributes["type"].Value,
                                           AdapterList = GetAdapters(component.AccountName, pluginNode.Attributes["taskGuid"].Value)
                                       })
                {
                    if (string.IsNullOrEmpty(plugin.TaskGuid))
                        throw new Exception(component.AccountName + "组件的插件配置节有为空必填项！");
                    component.Plugins.Add(plugin);
                }
                foreach (var syn in from XmlNode synNode in synServiceList
                                    select new SynService
                                    {
                                        TaskGuid = synNode.Attributes["taskGuid"] == null ? string.Empty : synNode.Attributes["taskGuid"].Value,
                                        DataTypes = synNode.Attributes["dataTypes"] == null ? string.Empty : synNode.Attributes["dataTypes"].Value,
                                        TaskList = GetTasks(component.AccountName, synNode.Attributes["taskGuid"].Value)
                                    })
                {
                    if (string.IsNullOrEmpty(syn.TaskGuid))
                        throw new Exception(component.AccountName + "组件的同步服务配置节有为空必填项！");
                    component.SynServices.Add(syn);
                }
                //try
                //{
                //    component.IsOrg = true;
                //    if (null == componentNode.Attributes["orgUrl"])
                //    {
                //        component.IsOrg = false;
                //        var orgTask = component.Tasks.Find(t => t.TaskGuid.Equals(Constants.ORG_GUID));
                //        component.OrgUrl = component.Adapters.Find(t => t.Guid.Equals(orgTask.AdapterGuid)).Protocol;
                //        if (string.IsNullOrEmpty(component.OrgUrl))
                //            throw new Exception("组织机构适配器配置异常！");
                //    }
                //}
                //catch (Exception e)
                //{
                //    if (!e.Message.Contains("组织机构"))
                //        throw new Exception("组织机构适配器配置异常！");
                //    throw;
                //}
                return component;
            }
            catch (Exception e)
            {
                LoggerHelper.WriteCodePointInfo(e.Message);
                LoggerHelper.WriteStackTraceInfo(e.StackTrace);
                return null;
            }
        }

        public IList<Adapter>GetAdapters(string accountName,string taskGuid)
        {
            var adapterList =
                _xmlDoc.SelectNodes("//component[@accountName='" + accountName + "']/plugin[@taskGuid='" +
                                            taskGuid + "']/adapter");
            var list = new List<Adapter>();
            if (null == adapterList || adapterList.Count == 0)
                throw new Exception(accountName + "组件的插件配置节错误！");
            foreach (var adapter in from XmlNode adapterNode in adapterList
                                    select new Adapter
                                    {
                                        Guid = adapterNode.Attributes["guid"].Value??string.Empty
                                    })
            {
                if (string.IsNullOrEmpty(adapter.Guid))
                    throw new Exception(accountName + "组件的插件配置节有为空必填项");
                list.Add(adapter);
            }
            return list;
        }
                                  
        public List<Task> GetTasks(string accountName,string taskGuid)
        {
            var taskList =
                _xmlDoc.SelectNodes("//component[@accountName='" + accountName + "']/synService[taskGuid='" +
                                    taskGuid + "']/task");
            if (null == taskList || taskList.Count == 0)
                throw new Exception(accountName + "组件的同步服务配置节错误");
            var list = new List<Task>();
            foreach(var task in from XmlNode taskNode in taskList
                    select new Task
                                {
                                    TaskGuid =taskNode.Attributes["guid"].Value??string.Empty
                                })
            {
                if (string.IsNullOrEmpty(task.TaskGuid))
                    throw new Exception(accountName + "组件的同步服务配置节有为空必填项");
                list.Add(task);
            }
            return list;
        }

        public Component GetComponentInfo(string accountName)
        {
            var componentList = _xmlDoc.GetElementsByTagName("components");
            if (componentList.Count == 0)
                return null;
            foreach(XmlNode componentNode in componentList)
            {
                var node = componentNode.SelectSingleNode("//component[@accountName='" + accountName + "']");
                if (null == node) continue;
                Component result;
                if (null!=node.Attributes["orgUrl"])//判断是否是组织机构组件
                {
                    result = new Component
                                 {
                                     AccountName = node.Attributes["accountName"].Value,
                                     Password = node.Attributes["password"].Value,
                                     CertName = node.Attributes["certName"].Value,
                                     OrgUrl = node.Attributes["orgUrl"].Value
                                 };
                }
                else
                {
                    var orgTaskGuid = node.SelectSingleNode("task[@taskGuid='" + Constants.ORG_GUID + "']").Attributes["adapterGuid"].Value;
                    result = new Component
                    {
                        AccountName = node.Attributes["accountName"].Value,
                        Password = node.Attributes["password"].Value,
                        CertName = node.Attributes["certName"].Value,
                        OrgUrl = node.SelectSingleNode("adapter[@guid='" + orgTaskGuid + "']").Attributes["protocol"].Value
                    };
                }
                return result;
            }
            return null;
        }

        public Adapter GetAdapterByTaskGuid(string accountName,string taskGuid)
        {
            var task = _xmlDoc.SelectSingleNode("components/component[@accountName='"+accountName+"']/task[@taskGuid='" + taskGuid + "']");
            if (null==task)
            {
                return new Adapter { Guid = string.Empty, Type = "SZJT.Framework.Adapter.LocalAdapterBase,SZJT.Framework" };
            }
            var adapter = _xmlDoc.SelectSingleNode("components/component/adapter[@guid='" + task.Attributes["adapterGuid"].Value + "']");
            return new Adapter
                       {
                           Guid = adapter.Attributes["guid"].Value,
                           Type = adapter.Attributes["type"].Value,
                           Protocol = null == adapter.Attributes["protocol"] ? string.Empty : adapter.Attributes["protocol"].Value
                       };
        }

        /// <summary>
        /// 证书配置集合
        /// </summary>
        /// <returns></returns>
        public List<CertEntity> GetCertList()
        {  
            var list = new List<CertEntity>();
            var nodeCollection = _xmlDoc.GetElementsByTagName("certificate");
            foreach (XmlNode node in nodeCollection)
            {
                var entity = new CertEntity();
                if(!string.IsNullOrEmpty(node.Attributes["findValue"].InnerText))
                    entity.FindValue = node.Attributes["findValue"].InnerText;
                if (!string.IsNullOrEmpty(node.Attributes["findType"].InnerText))
                    entity.FindType = node.Attributes["findType"].InnerText;
                if (!string.IsNullOrEmpty(node.Attributes["storeLocation"].InnerText))
                    entity.StoreLocation = node.Attributes["storeLocation"].InnerText;
                if (!string.IsNullOrEmpty(node.Attributes["storeName"].InnerText))
                    entity.StoreName = node.Attributes["storeName"].InnerText;
                list.Add(entity);
            }
            return list;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="certName"></param>
        /// <returns></returns>
        public CertEntity GetCert(string certName)
        {
            var list = GetCertList();
            if(null==list||list.Count==0)
            {
                LoggerHelper.WriteCodePointInfo("组件未配置证书信息");
                return null;
            }
            return list.Find(c => c.FindValue == certName);
        }
    }
}
